package com.piaoniu.open.utils;

import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;

/**
 * Created with IntelliJ IDEA.
 * Description:
*
 * @author: daniel
 * @creed: keep it simple and stupid !
 * @Time: 2019/6/12 1:33 PM
 */
@Slf4j
public class ReflectionUtils {

    public static final String GETTER_PREFIX = "get";
    public static final String BOOLEAN_GETTER_PREFIX = "is";
    public static final String OBJECT_CLASS_NAME = "java.lang.Object";

    private static boolean isBoolean(Field field) {
        return field.getType().getName().equals("boolean") || field.getType().getName().equals("Boolean");
    }

    /**
     * 使用限制条件
     * 1.非继承
     *
     * @param clazz
     * @return
     */
    public static Map<Field, Method> getFieldGetters(Class clazz) {
        LinkedList<Class> classHierachy = getClassHierachy(clazz);
        Map<Field, Method> fieldMethodMap = new HashMap<>();
        classHierachy.forEach(e -> {
            Field[] declaredFields = e.getDeclaredFields();
            for (Field field : declaredFields) {
                String name = field.getName();
                try {
                    //获取对应field的getter
                    String getterPrefix = isBoolean(field) ? BOOLEAN_GETTER_PREFIX : GETTER_PREFIX;
                    Method getter = e.getMethod(getterPrefix + name.substring(0, 1).toUpperCase() + name.substring(1), new Class[]{});
                    fieldMethodMap.put(field, getter);
                } catch (NoSuchMethodException exp) {
                    log.info("missing getter for field :{}", name);
                }
            }
        });

        return fieldMethodMap;
    }

    private static LinkedList<Class> getClassHierachy(Class clazz) {
        LinkedList<Class> classList= new LinkedList<>();
        classList.add(clazz);
        Class superclass = clazz.getSuperclass();
        if (!OBJECT_CLASS_NAME.equals(superclass.getName())) {
            classList.addAll(getClassHierachy(superclass));
        }
        return classList;

    }
}
